package com.hillky.channelhandler.handler;

import com.hillky.compress.Compressor;
import com.hillky.compress.CompressorFactory;
import com.hillky.serialize.Serializer;
import com.hillky.serialize.SerializerFactory;
import com.hillky.transport.message.MessageFormatConstant;
import com.hillky.transport.message.YrpcRequest;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.extern.slf4j.Slf4j;

/**
 * 4B magic（魔数） --->yrpc.getV=Bytes()
 * 1B version(版本)  ---> 1
 * 2B header length ---> 首部的长度
 * 4B full length 报文总长度
 * 1B serialize
 * 1B compress
 * 1B requestType
 * 8B requestId
 *
 * body
 *
 *
 * 出站时第一个处理器，进行编码
 */
@Slf4j
public class YrpcRequestEncoder extends MessageToByteEncoder<YrpcRequest> {


    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, YrpcRequest yrpcRequest, ByteBuf byteBuf) throws Exception {
        // 4个字节的魔数
        byteBuf.writeBytes(MessageFormatConstant.MAGIC);

        //版本
        byteBuf.writeByte(MessageFormatConstant.VERSION);

        //2个字节的头部胀肚
        byteBuf.writeShort(MessageFormatConstant.HEADER_LENGTH);

        // todo 总长度不清楚，不知道body长度
        byteBuf.writerIndex(byteBuf.writerIndex()+MessageFormatConstant.FULL_FIELD_LENGTH);

        //3个类型
        byteBuf.writeByte(yrpcRequest.getRequestType());
        byteBuf.writeByte(yrpcRequest.getSerializeType());
        byteBuf.writeByte(yrpcRequest.getCompressType());

        //8字节的请求id
        byteBuf.writeLong(yrpcRequest.getRequestId());
        byteBuf.writeLong(yrpcRequest.getTimeStamp());


        // 如果不是心跳请求，就处理请求体
//        if(yrpcRequest.getRequestType()!= RequestType.HEART_BEAT.getId()){
//            //处理一下总长度，其实总长度=header长度
//            //先保存当前写指针的位置
//            int writerIndex = byteBuf.writerIndex();
//            //将写指针的位置移动到总长度的位置上
//            byteBuf.writerIndex(MessageFormatConstant.MAGIC.length+MessageFormatConstant.VERSION_LENGTH+MessageFormatConstant.HEADER_FIELD_LENGTH);
//            byteBuf.writeInt(MessageFormatConstant.HEADER_LENGTH);
//            //将写指针归位
//            byteBuf.writerIndex(writerIndex);
//            return;
//        }

        //写入请求体（requestPayload），


        byte[] body=null;

        // 2.序列化结束根据配置的方式进行压缩
        if(yrpcRequest.getRequestPayload()!=null){
            // 1.根据配置的方式进行序列化
            // 怎么实现序列化
            // 工具类耦合性比较高，如果需要替换序列化的方式会很难，工具写死序列化方式
            Serializer serializer= SerializerFactory.getSerializer(yrpcRequest.getSerializeType()).getImpl();
            body= serializer.serialize(yrpcRequest.getRequestPayload());

            Compressor compressor= CompressorFactory.getCompressor(yrpcRequest.getCompressType()).getImpl();
            body = compressor.compress(body);
        }

        if(body!=null){
            byteBuf.writeBytes(body);
        }

        int bodyLength=body==null?0:body.length;

        //重新处理报文总长度
        //先保存当前写指针的位置
        int writerIndex = byteBuf.writerIndex();
        //将写指针的位置移动到总长度的位置上
        byteBuf.writerIndex(MessageFormatConstant.MAGIC.length+MessageFormatConstant.VERSION_LENGTH+MessageFormatConstant.HEADER_FIELD_LENGTH);
        byteBuf.writeInt(MessageFormatConstant.HEADER_LENGTH+bodyLength);
        //将写指针归位
        byteBuf.writerIndex(writerIndex);

        if(log.isDebugEnabled()){
            log.debug("请求【{}】已经完成报文编码",yrpcRequest.getRequestId());
        }

    }


}
